﻿using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
using System.ComponentModel;
using System.Runtime.Serialization;

namespace ServerNodeLib
{
	/// <summary>
	/// This is the primary contract for the simple scheduler server.
	/// 
	/// The communication model is server-centric so that individual client
	/// nodes do not have to open up firewall ports or deal with NAT stuff.
	/// 
	/// The client initiates all communication with the server.
	/// </summary>
	[ServiceContract(Namespace = "http://esquared.unl.edu/jschulma", Name = "ISchedulerServer", ProtectionLevel = System.Net.Security.ProtectionLevel.None)]
	public interface ISchedulerServer
	{
		#region discovery stuff
		/// <summary>
		/// Announces to the discovery server that this node exists
		/// This is the first step in the communication chain.
		/// The server returns a guid which the client must use to identify itself.
		/// The client provides a "user-friendly" name.  The name need not be unique.
		/// </summary>
		/// <param name="name">The client node's name</param>
		/// <returns>The guid the server uses to identify this client</returns>
		[OperationContract(ProtectionLevel = System.Net.Security.ProtectionLevel.None)]
		Guid AnnounceMyself(String name);

		/// <summary>
		/// Announces to the server that the client is no longer available.
		/// The server will free up any resources it may have allocated to the client.
		/// The guid is no longer valid for any operation.
		/// </summary>
		/// <param name="nodeId">The server's guid of the client</param>
		/// <returns>True upon success</returns>
		[OperationContract(ProtectionLevel = System.Net.Security.ProtectionLevel.None)]
		bool UnAnnounceMyself(Guid nodeId);
		
		/// <summary>
		/// Replaces the status of the node with the new one.
		/// The method is called "Set" instead of "Update" to convey that
		/// any information sent in the newStatus will overwrite  ALL of the
		/// old status.  Updating, to me at least, implies that it is somewhat
		/// intelligent about the new information.  This is not the case with
		/// this message.  All old information is lost and the new information
		/// is assumed correct.
		/// 
		/// Second, this is the only mechanism in which the server sends
		/// information to the client.  The ActionRequest object long-term
		/// will contain more advanced commands.
		/// </summary>
		/// <param name="nodeId">The server's guid of the client</param>
		/// <param name="newStatus">The new status of the client</param>
		/// <returns>The action the server requests of the client to complete</returns>
		[OperationContract(ProtectionLevel = System.Net.Security.ProtectionLevel.None)]
		ActionRequest SetStatus(Guid nodeId, NodeStatus newStatus);

		/// <summary>
		/// Retrieves the particular client status.
		/// </summary>
		/// <param name="nodeId">The server's guid of the client</param>
		/// <returns>The node status object</returns>
		[OperationContract(ProtectionLevel = System.Net.Security.ProtectionLevel.None)]
		NodeStatus GetStatus(Guid nodeId);

		/// <summary>
		/// Returns a list of nodes that this service knows about.
		/// </summary>
		/// <returns>The list of node ids</returns>
		[OperationContract(ProtectionLevel = System.Net.Security.ProtectionLevel.None)]
		List<Guid> GetAllNodes();
		#endregion

		#region job management
		/// <summary>
		/// Returns the next available batch job for the client to complete.
		/// The server marks the returned batch as "started" by the client.
		/// </summary>
		/// <returns>The batch information</returns>
		[OperationContract(ProtectionLevel = System.Net.Security.ProtectionLevel.None)]
		BatchInfo GetAvailableBatchJob(Guid clientGuid);
		#endregion

		#region file transfer stuff
		/// <summary>
		/// A client asks the server to send a chunk of the latest version of the resource.
		/// The file transfer mechanism is done in chunks to avoid the arbitrary WCF
		/// file transfer limits.
		/// 
		/// That said, this method shouldn't be used to send hundreds of megabytes.
		/// Primarily I'm thinking of sub 10Mb files -- logs mostly.  If you need more
		/// information sent, consider executing a zip command and transfering the zip.
		/// </summary>
		/// <param name="batchId">The batch Id from where this request is made</param>
		/// <param name="destName">The destination path which uniquely identifies the resource.</param>
		/// <param name="chunkNum">The 0-based index of which chunk to return.</param>
		/// <returns>The raw data of the resource chunk</returns>
		[OperationContract(ProtectionLevel = System.Net.Security.ProtectionLevel.None)]
		byte[] GetResourceChunk(Guid batchId, String destName, int chunkNum);
		#endregion

		#region results
		/// <summary>
		/// Client sends the summary result info to the server.
		/// 
		/// This is the last message in the batch lifecycle.
		/// Upon receipt of a successful result, the server may free any
		/// resources associated with the batch and its group.
		/// 
		/// The client may not sent any further results or resources
		/// related to this batch
		/// </summary>
		/// <param name="batchId">The batch id this result is associated with.</param>
		/// <param name="result">The extended information of the result.</param>
		/// <returns>The result id, needed for transfering resources to the server.</returns>
		[OperationContract(ProtectionLevel = System.Net.Security.ProtectionLevel.None)]
		Guid PostResult(Guid batchId, ResultInfo result);

		/// <summary>
		/// Client sends a chunk of the result resource to the server.
		/// 
		/// This is identical to the GetResourceChunk method except the
		/// file goes to the server.
		/// </summary>
		/// <param name="chunkNum">The 0-based index of the chunk</param>
		/// <param name="batchId">The batch id</param>
		/// <param name="clientPath">The client's path of the resource</param>
		/// <param name="data">The raw data</param>
		/// <returns>True upon successful receipt</returns>
		[OperationContract(ProtectionLevel = System.Net.Security.ProtectionLevel.None)]
		bool PostResourceChunk(Guid batchId, String clientPath, int chunkNum, byte[] data);
		#endregion
	}
}
